﻿using System.Collections.Generic;
using UnityEngine;
using System.Linq;

namespace Yoozoo.Mars.Got
{
    public static class RendererExtensions
    {
        public static bool isVisible(this Renderer renderer, Camera camera)
        {
            Plane[] planes = GeometryUtility.CalculateFrustumPlanes(camera);
            return GeometryUtility.TestPlanesAABB(planes, renderer.bounds);
        }
    }

    public static class GameObjectExtensions
    {
        private static Dictionary<GameObject, Dictionary<System.Type, object>> s_GameObjectParentComponentMap = new Dictionary<GameObject, Dictionary<System.Type, object>>();
        public static T GetOrAddCompoment<T>(this GameObject gameobject) where T : Component
        {
            T result = gameobject.GetComponent<T>();
            if (result == null)
            {
                result = gameobject.AddComponent<T>();
            }
            return result;
        }

        public static void SetLayerRecursively(this GameObject gameObject, int layer)
        {
            gameObject.layer = layer;
            for (int i = 0, imax = gameObject.transform.childCount; i < imax; i++)
            {
                SetLayerRecursively(gameObject.transform.GetChild(i).gameObject, layer);
            }
        }
        public static T GetCachedParentComponent<T>(this GameObject gameObject)
        {
            Dictionary<System.Type, object> dictionary;
            if (GameObjectExtensions.s_GameObjectParentComponentMap.TryGetValue(gameObject, out dictionary))
            {
                object cachedParentComponent;
                if (dictionary.TryGetValue(typeof (T), out cachedParentComponent))
                    return (T) cachedParentComponent;
            }
            else
            {
                dictionary = new Dictionary<System.Type, object>();
                GameObjectExtensions.s_GameObjectParentComponentMap.Add(gameObject, dictionary);
            }
            T componentInParent = gameObject.GetComponentInParent<T>();
            dictionary.Add(typeof (T), (object) componentInParent);
            return componentInParent;
        }
        public static T[] GetComponentsInChildrenWithoutSelf<T>(this GameObject self) where T : Component
        {
            return self.GetComponentsInChildren<T>().Where(c => self != c.gameObject).ToArray();
        }
    }

    public static class TransformExtensions
    {
        public static T[] GetComponentsInChildrenWithoutSelf<T>(this Transform self) where T : Component
        {
            return self.GetComponentsInChildren<T>().Where(c => self != c.transform).ToArray();
        }
    }

    public static class ComponentExtensions
    {
        public static T AddComponent<T>(this Component component) where T : Component
        {
            return component.gameObject.AddComponent<T>();
        }

        public static T GetOrAddCompoment<T>(this Component component) where T : Component
        {
            T result = component.GetComponent<T>();
            if (result == null)
            {
                result = component.AddComponent<T>();
            }
            return result;
        }
    }


    public struct Vector4Int
    {
        public int StartX;
        public int StartY;
        public int MaxX;
        public int MaxY;
    }
}